/**
 * @file market_maker.h
 * @brief 做市商策略类的定义
 * 
 * @details 该文件定义了做市商策略类，该策略基于特征引擎计算的公平市场价格，
 * 在盘口附近主动提供流动性。当公平价格与盘口价格的差距超过阈值时，
 * 策略会调整被动订单的价格。该策略主要关注订单簿更新事件，而不对交易事件做出反应。
 * 
 * @author 原作者
 * @date 2023
 */

#pragma once

#include "common/macros.h"
#include "common/logging.h"

#include "order_manager.h"
#include "feature_engine.h"

using namespace Common;

namespace Trading {
  /**
   * @brief 做市商策略类
   * 
   * @details 该类实现了一种交易策略，通过监控订单簿变化并利用特征引擎计算的公平市场价格，
   * 在盘口附近主动提供流动性。当公平价格与盘口价格的差距超过配置的阈值时，
   * 策略会调整被动订单的价格。该策略主要关注订单簿更新事件，而不对交易事件做出实质性反应。
   */
  class MarketMaker {
  public:
    /**
     * @brief 构造函数
     * 
     * @details 初始化做市商策略对象，设置必要的组件和配置，并将策略的回调函数注册到交易引擎中。
     * 
     * @param logger 日志记录器指针，用于记录策略执行过程和结果
     * @param trade_engine 交易引擎指针，用于注册策略的回调函数
     * @param feature_engine 特征引擎指针，用于获取策略所需的公平市场价格
     * @param order_manager 订单管理器指针，用于发送和管理策略的订单
     * @param ticker_cfg 交易配置映射，包含每个证券的交易参数（如阈值、批量等）
     */
    MarketMaker(Common::Logger *logger, TradeEngine *trade_engine, const FeatureEngine *feature_engine,
                OrderManager *order_manager,
                const TradeEngineCfgHashMap &ticker_cfg);

    /**
     * @brief 处理订单簿更新
     * 
     * @details 该方法是做市商策略的核心逻辑，它处理订单簿更新事件，获取特征引擎计算的公平市场价格，
     * 并将其与交易阈值进行比较。根据公平价格与盘口价格的差距，策略会调整被动订单的价格。
     * 具体流程如下：
     * 1. 获取当前盘口状态和公平市场价格
     * 2. 验证盘口价格和公平市场价格的有效性
     * 3. 从配置中获取相应证券的批量和阈值
     * 4. 根据公平价格与盘口价格的差距计算新的买卖价格
     * 5. 调用订单管理器移动订单到新的价格位置
     * 
     * @param ticker_id 证券标识符
     * @param price 变化的价格
     * @param side 变化的买卖方向
     * @param book 市场订单簿指针，包含当前的盘口状态
     * 
     * @note 该方法不会抛出异常，使用 noexcept 修饰符来提高性能
     */
    auto onOrderBookUpdate(TickerId ticker_id, Price price, Side side, const MarketOrderBook *book) noexcept -> void {
      logger_->log("%:% %() % ticker:% price:% side:%\n", __FILE__, __LINE__, __FUNCTION__,
                   Common::getCurrentTimeStr(&time_str_), ticker_id, Common::priceToString(price).c_str(),
                   Common::sideToString(side).c_str());

      const auto bbo = book->getBBO();
      const auto fair_price = feature_engine_->getMktPrice();

      if (LIKELY(bbo->bid_price_ != Price_INVALID && bbo->ask_price_ != Price_INVALID && fair_price != Feature_INVALID)) {
        logger_->log("%:% %() % % fair-price:%\n", __FILE__, __LINE__, __FUNCTION__,
                     Common::getCurrentTimeStr(&time_str_),
                     bbo->toString().c_str(), fair_price);

        const auto clip = ticker_cfg_.at(ticker_id).clip_;
        const auto threshold = ticker_cfg_.at(ticker_id).threshold_;

        const auto bid_price = bbo->bid_price_ - (fair_price - bbo->bid_price_ >= threshold ? 0 : 1);
        const auto ask_price = bbo->ask_price_ + (bbo->ask_price_ - fair_price >= threshold ? 0 : 1);

        START_MEASURE(Trading_OrderManager_moveOrders);
        order_manager_->moveOrders(ticker_id, bid_price, ask_price, clip);
        END_MEASURE(Trading_OrderManager_moveOrders, (*logger_));
      }
    }

    /**
     * @brief 处理交易事件
     * 
     * @details 对于做市商策略，该方法仅记录交易事件信息，不执行实际的交易操作。
     * 该策略主要基于订单簿更新做出决策，而不是交易事件。
     * 
     * @param market_update 市场更新指针，包含交易信息
     * @param book 市场订单簿指针（本方法未使用）
     * 
     * @note 该方法不会抛出异常，使用 noexcept 修饰符来提高性能
     */
    auto onTradeUpdate(const Exchange::MEMarketUpdate *market_update, MarketOrderBook * /* book */) noexcept -> void {
      logger_->log("%:% %() % %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_),
                   market_update->toString().c_str());
    }

    /**
     * @brief 处理订单更新
     * 
     * @details 处理策略发送的订单的客户端响应。该方法记录订单响应信息，
     * 并将其转发给订单管理器进行处理。这样可以确保订单管理器维护正确的订单状态。
     * 
     * @param client_response 客户端响应指针，包含订单状态更新信息
     * 
     * @note 该方法不会抛出异常，使用 noexcept 修饰符来提高性能
     */
    auto onOrderUpdate(const Exchange::MEClientResponse *client_response) noexcept -> void {
      logger_->log("%:% %() % %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_),
                   client_response->toString().c_str());

      START_MEASURE(Trading_OrderManager_onOrderUpdate);
      order_manager_->onOrderUpdate(client_response);
      END_MEASURE(Trading_OrderManager_onOrderUpdate, (*logger_));
    }

    /**
     * @brief 已删除的构造函数和赋值运算符
     * 
     * @details 为了防止意外复制或移动做市商策略对象，禁用了默认构造函数、复制构造函数、
     * 移动构造函数以及复制赋值和移动赋值运算符。
     * 做市商策略对象应该始终使用显式的参数初始化。
     */
    MarketMaker() = delete;

    MarketMaker(const MarketMaker &) = delete;

    MarketMaker(const MarketMaker &&) = delete;

    MarketMaker &operator=(const MarketMaker &) = delete;

    MarketMaker &operator=(const MarketMaker &&) = delete;

  private:
    /**
     * @brief 特征引擎指针
     * 
     * @details 驱动做市商策略的特征引擎指针，用于获取公平市场价格等特征值。
     * 该指针不拥有特征引擎对象的所有权，因此声明为 const。
     */
    const FeatureEngine *feature_engine_ = nullptr;

    /**
     * @brief 订单管理器指针
     * 
     * @details 用于管理做市商策略的被动订单的订单管理器指针。
     * 该策略通过调用 moveOrders 方法来维护其被动订单。
     */
    OrderManager *order_manager_ = nullptr;

    /**
     * @brief 时间字符串缓存
     * 
     * @details 用于日志记录的时间字符串缓存，避免重复创建时间字符串
     */
    std::string time_str_;
    
    /**
     * @brief 日志记录器指针
     * 
     * @details 用于记录策略执行过程和结果的日志记录器指针
     */
    Common::Logger *logger_ = nullptr;

    /**
     * @brief 交易配置映射
     * 
     * @details 保存做市商策略的交易配置，包含每个证券的交易参数，
     * 如阈值（threshold_）和批量（clip_）。该映射在构造函数中初始化，且不可修改，
     * 因此声明为 const。
     */
    const TradeEngineCfgHashMap ticker_cfg_;
  };
}
